package com.itheima.nio.tomcat.parse;

import com.itheima.nio.tomcat.exception.IsNotImplementsHttpServletException;
import com.itheima.nio.tomcat.inter.HttpServlet;
import com.itheima.nio.tomcat.inter.PraseServletConfig;
import com.itheima.nio.tomcat.inter.ServletConcurrentHashMap;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;

/**
 * 解析xml文件的类
 */
public class XmlParseServletConfig implements PraseServletConfig {

    // 定义web.xml文件的路径
    public static final String WEB_XML_PATH = "itheima-nio-tomcat\\webapp\\WEB-INF\\web.xml" ;

    @Override
    public void parse() {

        /**
         * 1. 创建解析器对象(SAXReader)
         * 2. 读取web.xml配置文件，获取Document对象
         * 3. 获取根节点元素对象
         * 4. 创建一个HashMap集合对象(键String类型 ， 值String类型)，用来存储servlet的配置信息
         * 5. 获取根元素对象下所有的<servlet>元素对象集合
         * 6. 遍历集合获取每一个<servlet>元素对象
         *   6.1 获取该<servlet>元素下的<servlet-name>元素对象，并且获取标签体内容
         *   6.2 获取该<servlet>元素下的<servlet-class>元素对象，并且获取标签体内容
         *   6.3 将获取到的数据存储到HashMap集合对象中
         */
        try {

            // 1. 创建解析器对象(SAXReader)
            SAXReader saxReader = new SAXReader() ;

            // 2. 读取web.xml配置文件，获取Document对象
            Document document = saxReader.read(new FileInputStream(WEB_XML_PATH));

            // 3. 获取根节点元素对象
            Element rootElement = document.getRootElement();

            // 4. 创建一个HashMap集合对象(键String类型 ， 值String类型)，用来存储servlet的配置信息
            HashMap<String , String> hashMap = new HashMap<String , String>() ;

            // 5. 获取根元素对象下所有的<servlet>元素对象集合
            List<Element> servletInfos = rootElement.elements("servlet");

            // 6. 遍历集合获取每一个<servlet>元素对象
            for(Element servlet : servletInfos) {

                // 6.1 获取该<servlet>元素下的<servlet-name>元素对象，并且获取标签体内容
                String servletName = servlet.element("servlet-name").getText();

                // 6.2 获取该<servlet>元素下的<servlet-class>元素对象，并且获取标签体内容
                String servletClassName = servlet.element("servlet-class").getText();

                // 6.3 将获取到的数据存储到HashMap集合对象中
                hashMap.put(servletName , servletClassName) ;
            }


            /**
             * 1. 获取根节点元素对象下所有的<servlet-mapping>元素对象集合
             * 2. 遍历这个集合对象，获取每一个<servlet-mapping>元素对象
             *    2.1 获取<servlet-mapping>元素对象下的<servlet-name>元素对象，并获取标签体内容
             *    2.2 获取<servlet-mapping>元素对象下的<url-pattern>元素对象，并获取标签体内容
             *    2.3 根据<servlet-name>元素对象的标签体内容，从存储Servlet信息的HashMap集合中获取对应的Servlet的全类名
             *    2.4 通过反射创建这个Servlet对象
             *    2.5 判断该Servlet所实现的接口中，是否存在HttpServlet接口
             *    2.6 如果有就创建该类对象，将其存储到ServletConcurrentHashMap.conrrentHashMap中， 如果没有就抛出自定义异常，将异常信息打印到控制台。
             */

            // 1. 获取根节点元素对象下所有的<servlet-mapping>元素对象集合
            List<Element> servletMappingInfos = rootElement.elements("servlet-mapping");

            // 2. 遍历这个集合对象，获取每一个<servlet-mapping>元素对象
            for(Element servletMappingInfo : servletMappingInfos) {

                // 2.1 获取<servlet-mapping>元素对象下的<servlet-name>元素对象，并获取标签体内容
                String servletName = servletMappingInfo.element("servlet-name").getText();

                // 2.2 获取<servlet-mapping>元素对象下的<url-pattern>元素对象，并获取标签体内容
                String urlPattern = servletMappingInfo.element("url-pattern").getText();

                // 2.3 根据<servlet-name>元素对象的标签体内容，从存储Servlet信息的HashMap集合中获取对应的Servlet的全类名
                String servletClassName = hashMap.get(servletName);

                // 2.4 通过反射创建这个Servlet对象
                Class servletClazz = Class.forName(servletClassName);

                // 2.5 判断该Servlet所实现的接口中，是否存在HttpServlet接口
                boolean flag = false ;                                  // 作用：记录当前这个servlet所实现的接口中是否包含HttpServlet接口
                Class[] interfaces = servletClazz.getInterfaces();
                for(Class clazz : interfaces) {
                    if(clazz == HttpServlet.class) {
                        flag = true ;
                        break;
                    }
                }

                if(flag) {

                    HttpServlet httpServlet = (HttpServlet)servletClazz.newInstance();
                    ServletConcurrentHashMap.concurrentHashMap.put(urlPattern , httpServlet) ;

                }else {

                    try {
                        throw new IsNotImplementsHttpServletException(servletClazz.getName() + "is not implements HttpServlet interface ....") ;
                    }catch (IsNotImplementsHttpServletException e) {
                        e.printStackTrace();
                    }

                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
